import { Injectable, Logger } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { DataSource, Repository, EntityTarget, SelectQueryBuilder } from 'typeorm';

@Injectable()
export class AuroraReadWriteService {
  private readonly logger = new Logger(AuroraReadWriteService.name);

  constructor(
    @InjectDataSource('default') private readonly writerDataSource: DataSource,
    @InjectDataSource('reader') private readonly readerDataSource: DataSource,
  ) {}

  /**
   * 获取写库 Repository
   */
  getWriterRepository<Entity>(entity: EntityTarget<Entity>): Repository<Entity> {
    return this.writerDataSource.getRepository(entity);
  }

  /**
   * 获取读库 Repository
   */
  getReaderRepository<Entity>(entity: EntityTarget<Entity>): Repository<Entity> {
    return this.readerDataSource.getRepository(entity);
  }

  /**
   * 执行写操作 (INSERT, UPDATE, DELETE)
   */
  async executeWrite<T>(operation: (writerRepo: DataSource) => Promise<T>): Promise<T> {
    const startTime = Date.now();
    
    try {
      this.logger.debug('🔍 执行写操作');
      const result = await operation(this.writerDataSource);
      
      const duration = Date.now() - startTime;
      this.logger.debug(`✅ 写操作完成，耗时: ${duration}ms`);
      
      return result;
    } catch (error) {
      const duration = Date.now() - startTime;
      this.logger.error(`❌ 写操作失败，耗时: ${duration}ms`, error);
      throw error;
    }
  }

  /**
   * 执行读操作 (SELECT)
   */
  async executeRead<T>(operation: (readerRepo: DataSource) => Promise<T>): Promise<T> {
    const startTime = Date.now();
    
    try {
      this.logger.debug('📖 执行读操作');
      const result = await operation(this.readerDataSource);
      
      const duration = Date.now() - startTime;
      this.logger.debug(`✅ 读操作完成，耗时: ${duration}ms`);
      
      return result;
    } catch (error) {
      const duration = Date.now() - startTime;
      this.logger.warn(`⚠️ 读操作失败，尝试写库，耗时: ${duration}ms`);
      
      // 读库失败时回退到写库
      return this.executeWrite(operation);
    }
  }

  /**
   * 带读库回退的查询
   */
  async findWithFallback<Entity>(
    entity: EntityTarget<Entity>,
    options?: any
  ): Promise<Entity[]> {
    try {
      // 优先使用读库
      const readerRepo = this.getReaderRepository(entity);
      return await readerRepo.find(options);
    } catch (error) {
      this.logger.warn('读库查询失败，回退到写库');
      // 回退到写库
      const writerRepo = this.getWriterRepository(entity);
      return await writerRepo.find(options);
    }
  }

  /**
   * 事务操作 (仅写库)
   */
  async executeTransaction<T>(
    operation: (manager: any) => Promise<T>
  ): Promise<T> {
    return this.writerDataSource.transaction(async (manager) => {
      this.logger.debug('🔄 开始事务操作');
      const result = await operation(manager);
      this.logger.debug('✅ 事务操作完成');
      return result;
    });
  }

  /**
   * 检查连接健康状态
   */
  async healthCheck(): Promise<{
    writer: boolean;
    reader: boolean;
    latency: { writer: number; reader: number };
  }> {
    const results = {
      writer: false,
      reader: false,
      latency: { writer: 0, reader: 0 },
    };

    // 检查写库
    try {
      const writerStart = Date.now();
      await this.writerDataSource.query('SELECT 1');
      results.writer = true;
      results.latency.writer = Date.now() - writerStart;
    } catch (error) {
      this.logger.error('写库健康检查失败:', error);
    }

    // 检查读库
    try {
      const readerStart = Date.now();
      await this.readerDataSource.query('SELECT 1');
      results.reader = true;
      results.latency.reader = Date.now() - readerStart;
    } catch (error) {
      this.logger.error('读库健康检查失败:', error);
    }

    return results;
  }

  /**
   * 获取连接池状态
   */
  async getPoolStatus() {
    const getPoolInfo = (dataSource: DataSource, name: string) => {
      const pool = (dataSource.driver as any)?.master?.pool;
      if (!pool) return null;

      return {
        name,
        totalCount: pool.totalCount || 0,
        idleCount: pool.idleCount || 0,
        waitingCount: pool.waitingCount || 0,
        activeCount: (pool.totalCount || 0) - (pool.idleCount || 0),
      };
    };

    return {
      writer: getPoolInfo(this.writerDataSource, 'Writer'),
      reader: getPoolInfo(this.readerDataSource, 'Reader'),
      timestamp: new Date().toISOString(),
    };
  }
}

// 装饰器：自动选择读写库
export function UseReader() {
  return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
    const method = descriptor.value;
    descriptor.value = function (...args: any[]) {
      // 在方法执行前设置使用读库的标记
      (this as any)._useReader = true;
      const result = method.apply(this, args);
      delete (this as any)._useReader;
      return result;
    };
  };
}

export function UseWriter() {
  return function (target: any, propertyName: string, descriptor: PropertyDescriptor) {
    const method = descriptor.value;
    descriptor.value = function (...args: any[]) {
      // 在方法执行前设置使用写库的标记
      (this as any)._useWriter = true;
      const result = method.apply(this, args);
      delete (this as any)._useWriter;
      return result;
    };
  };
}

// 基础 Repository 类，自动处理读写分离
export abstract class BaseRepository<Entity> {
  constructor(
    protected readonly auroraService: AuroraReadWriteService,
    protected readonly entity: EntityTarget<Entity>,
  ) {}

  // 读操作
  async find(options?: any): Promise<Entity[]> {
    return this.auroraService.findWithFallback(this.entity, options);
  }

  async findOne(options: any): Promise<Entity | null> {
    return this.auroraService.executeRead(async (dataSource) => {
      const repo = dataSource.getRepository(this.entity);
      return repo.findOne(options);
    });
  }

  async count(options?: any): Promise<number> {
    return this.auroraService.executeRead(async (dataSource) => {
      const repo = dataSource.getRepository(this.entity);
      return repo.count(options);
    });
  }

  // 写操作
  async save(entity: Entity | Entity[]): Promise<Entity | Entity[]> {
    return this.auroraService.executeWrite(async (dataSource) => {
      const repo = dataSource.getRepository(this.entity);
      return repo.save(entity as any);
    });
  }

  async update(criteria: any, partialEntity: any): Promise<any> {
    return this.auroraService.executeWrite(async (dataSource) => {
      const repo = dataSource.getRepository(this.entity);
      return repo.update(criteria, partialEntity);
    });
  }

  async delete(criteria: any): Promise<any> {
    return this.auroraService.executeWrite(async (dataSource) => {
      const repo = dataSource.getRepository(this.entity);
      return repo.delete(criteria);
    });
  }

  // 创建查询构建器
  createQueryBuilder(alias?: string, useReader: boolean = true): SelectQueryBuilder<Entity> {
    const dataSource = useReader ? 
      this.auroraService['readerDataSource'] : 
      this.auroraService['writerDataSource'];
    
    return dataSource.getRepository(this.entity).createQueryBuilder(alias);
  }
}

/**
// 使用示例
@Injectable()
export class UserService extends BaseRepository<any> {
  constructor(auroraService: AuroraReadWriteService) {
    super(auroraService, 'User'); // 替换为实际的 User 实体
  }

  @UseReader()
  async getUserById(id: string) {
    return this.findOne({ where: { id } });
  }

  @UseReader()
  async searchUsers(keyword: string) {
    return this.createQueryBuilder('user', true) // true = 使用读库
      .where('user.name LIKE :keyword', { keyword: `%${keyword}%` })
      .getMany();
  }

  @UseWriter()
  async createUser(userData: any) {
    return this.save(userData);
  }

  @UseWriter()
  async updateUser(id: string, userData: any) {
    return this.update({ id }, userData);
  }

  // 复杂查询示例
  async getUsersWithPagination(page: number, limit: number) {
    return this.auroraService.executeRead(async (dataSource) => {
      const repo = dataSource.getRepository('User');
      return repo.find({
        skip: (page - 1) * limit,
        take: limit,
        order: { createdAt: 'DESC' },
      });
    });
  }

  // 事务示例
  async transferPoints(fromUserId: string, toUserId: string, points: number) {
    return this.auroraService.executeTransaction(async (manager) => {
      // 减少发送者积分
      await manager.decrement('User', { id: fromUserId }, 'points', points);
      // 增加接收者积分
      await manager.increment('User', { id: toUserId }, 'points', points);
      
      // 记录转账历史
      await manager.save('PointsTransfer', {
        fromUserId,
        toUserId,
        points,
        createdAt: new Date(),
      });
    });
  }
}

 */